home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.5 Applications 1999 May / SGI IRIX 6.5 Applications 1999 May.iso / dist / sitemgr.idb / usr / sitemgr / bin / html2ps.z / html2ps
Text File  |  1998-05-04  |  33KB  |  1,206 lines

  1. #!/usr/bin/perl
  2. #
  3. # This is html2ps 0.2 alpha PL5, an HTML-to-PostScript converter.
  4. #   Copyright (C) 1995 Jan Karrman.
  5. #
  6. #   This program is free software; you can redistribute it and/or modify
  7. #   it under the terms of the GNU General Public License as published by
  8. #   the Free Software Foundation; either version 2 of the License, or
  9. #   (at your option) any later version.
  10. #
  11. #   This program is distributed in the hope that it will be useful,
  12. #   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. #   GNU General Public License for more details.
  15. #
  16. #   You should have received a copy of the GNU General Public License
  17. #   along with this program; if not, write to the Free Software
  18. #   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. #
  20. # Author: Jan Karrman, Dept. of Scientific Computing, Uppsala University,
  21. #         Sweden, e-mail: jan@tdb.uu.se.
  22. #
  23. # 97Apr04  Greg Ferguson/gferg@sgi.com: added sgi extensions
  24. #
  25.  
  26.  
  27. # Set the following three variables to 1 or 0 if you have or have not the
  28. # corresponding package installed:
  29. $have_ImageMagick=0;
  30. $have_pbmplus=0;
  31. $have_netpbm=0;
  32. $have_djpeg=0;
  33. $have_sgi=1;
  34.  
  35. # You may have to change the names of the temporary directory and filename
  36. # if you are not on a UNIX system:
  37. $tmpdir="/tmp/";
  38. $tmpnam="h2p$$";
  39.  
  40. # No editing necessary below this line
  41.  
  42. $usage=<<EOU;
  43. Usage:
  44.  html2ps [-2aCcFgLnOTUuvX] [-B 0|1|2] [-b URL] [-cw program] [-f font]
  45.   [-hn scalefactor] [-i scalefactor] [-IM text] [-l length] [-LM size]
  46.   [-m scalefactor] [-MM size] [-N num] [-o file] [-p scalefactor] [-PS size]
  47.   [-s scalefactor] [-tn style] [-TM size] [-w width] [-x 0|1|2] [-zl text]
  48.   [-zr text] [URL|file]
  49. EOU
  50. $version="html2ps 0.2 alpha";
  51. $styles="Possible choices are: n, i, b, bi, f, fb, fi and fbi";
  52. $opts="2|a|c|C|F|g|L|n|O|T|u|U|v|X|B:|b:|s:|w:|l:|m:|p:|f:|o:|cw:|i:|IM:|PS:"
  53.  ."|LM:|TM:|MM:|h1:|h2:|h3:|h4:|h5:|h6:|t1:|t2:|t3:|t4:|t5:|t6:|x:|zl:|zr:|N:";
  54. $ulanch="t";
  55. $number="f";
  56. $mask=7;
  57. $opt_PS=29.7;
  58. $opt_LM=2.5;
  59. $opt_TM=3;
  60. $opt_MM=2;
  61. $opt_s=1;
  62. $opt_p=1;
  63. $opt_i=1;
  64. $opt_m=1;
  65. $opt_f="n";
  66. $opt_f="n";
  67. $opt_B=0;
  68. $opt_h1=1;
  69. $opt_h2=1;
  70. $opt_h3=1;
  71. $opt_h4=1;
  72. $opt_h5=1;
  73. $opt_h6=1;
  74. $opt_t1="b";
  75. $opt_t2="b";
  76. $opt_t3="b";
  77. $opt_t4="b";
  78. $opt_t5="b";
  79. $opt_t6="b";
  80. $ff="Courier";
  81. $fb="Courier-Bold";
  82. $fi="Courier-Oblique";
  83. $ft="Courier-BoldOblique";
  84. $opt_IM="[IMAGE]";
  85. $opt_N=1;
  86. $d=9;
  87. $f=72/2.54;
  88. $geturl="lynx -source";
  89. $geturl="/usr/sitemgr/bin/smgeturl" if($have_sgi);
  90. $giftopm="giftopnm"  if($have_netpbm);
  91. $giftopm="giftoppm"  if($have_pbmplus);
  92. $giftopm="fromgif"   if($have_sgi);
  93. $scr=$tmpdir.$tmpnam;
  94.  
  95. &Getopts($opts) || die $usage;
  96. die $usage if $opt_U;
  97. print STDERR "$version\n" if $opt_v;
  98. if ($opt_a) {$mask=0};
  99. if ($opt_n) {$number="t"};
  100. if ($opt_u) {$ulanch="f"};
  101. if ($opt_PS=~/^a4$/i) {$opt_PS=29.7};
  102. if ($opt_PS=~/^us$/i) {$opt_PS=27.9};
  103. if($d*$opt_s>15) {$d=int(15/$opt_s)};
  104. $twoup=$opt_2?"t":"f";
  105. $html=$ARGV[0];
  106. $lfoot="f";
  107. $rfoot="f";
  108. if ($opt_zl) {
  109.   $lfoot="t";
  110.   $opt_zl=~s/\$URL/$html/g;
  111. }
  112. if ($opt_zr) {
  113.   $rfoot="t";
  114.   $opt_zr=~s/\$URL/$html/g;
  115. }
  116.  
  117. if($opt_B!~/^[0-2]$/) {die "Illegal value for -B: $opt_B\n"}
  118. if($set_x && $opt_x!~/^[0-2]$/) {die "Illegal value for -x: $opt_x\n"}
  119. $F='-?\d*\.?\d*';
  120. for $o
  121.  ($opt_s,$opt_w,$opt_l,$opt_p,$opt_LM,$opt_TM,$opt_MM,$opt_PS,$opt_i,$opt_m,
  122.   $opt_N,$opt_h1,$opt_h2,$opt_h3,$opt_h4,$opt_h5,$opt_h6)
  123.   {die "Non numeric: $o\n" if($o!~/^$F$/)}
  124.  
  125. if($opt_2) {
  126.   $opt_L=1;
  127.   $opt_s=0.65*$opt_s;
  128. }
  129. $opt_N=int($opt_N);
  130. $opt_N--;
  131. $mm=int($opt_MM*$f);
  132. $is=0.8*$opt_i;
  133. $msc=1/$opt_s;
  134. $mag=1000*$opt_m*$opt_s;
  135.  
  136. $h1=19*$opt_h1;
  137. $h2=17*$opt_h2;
  138. $h3=15*$opt_h3;
  139. $h4=14*$opt_h4;
  140. $h5=13*$opt_h5;
  141. $h6=12*$opt_h6;
  142.  
  143. if ($opt_L) {
  144.   $opt_w=$opt_2?11.5:24.5 unless $opt_w;
  145.   $opt_l=15 unless $opt_l;
  146.   $xc=int($opt_TM*$f);
  147.   $yc=int($opt_LM*$f);
  148.   $w=int($opt_w*$f);
  149.   $l=int($opt_l*$f);
  150.   $rot=" 90 rotate"
  151. }
  152. else {
  153.   $opt_w=16 unless $opt_w;
  154.   $opt_l=23 unless $opt_l;
  155.   $xc=int($opt_LM*$f);
  156.   $yc=int(($opt_PS-$opt_TM)*$f);
  157.   $w=int($opt_w*$f);
  158.   $l=int($opt_l*$f)
  159. }
  160. if ($opt_F) {
  161.   $xr=int($w/$opt_s)+$d;
  162.   $yb=-int($l/$opt_s)-$d;
  163.   $fr="\n gsave 1 setlinejoin -$d $d M $xr $d L $xr $yb L -$d $yb L -$d $d L"
  164.      ."\n closepath stroke grestore"
  165. }
  166.  
  167. if($opt_x==0 && defined $opt_x) {
  168.   $dupl="statusdict /setduplexmode known\n"
  169.         ." {statusdict begin false setduplexmode end} if"
  170. }
  171. if($opt_x==1) {
  172.   $dupl="statusdict /setduplexmode known\n"
  173.         ." {statusdict begin true setduplexmode end} if"
  174. }
  175. if($opt_x==2) {
  176.   $dupl="statusdict /settumble known\n"
  177.         ." {statusdict begin true setduplexmode true settumble end} if"
  178. }
  179.  
  180. @n=(
  181.  "NewCenturySchlbk-Roman",
  182.  "NewCenturySchlbk-Bold",
  183.  "NewCenturySchlbk-Italic",
  184.  "NewCenturySchlbk-BoldItalic");
  185. @t=(
  186.  "Times-Roman",
  187.  "Times-Bold",
  188.  "Times-Italic",
  189.  "Times-BoldItalic");
  190. @h=(
  191.  "Helvetica",
  192.  "Helvetica-Bold",
  193.  "Helvetica-Oblique",
  194.  "Helvetica-BoldOblique");
  195. @hn=(
  196.  "Helvetica-Narrow",
  197.  "Helvetica-Narrow-Bold",
  198.  "Helvetica-Narrow-Oblique",
  199.  "Helvetica-Narrow-BoldOblique");
  200. @p=(
  201.  "Palatino-Roman",
  202.  "Palatino-Bold",
  203.  "Palatino-Italic",
  204.  "Palatino-BoldItalic");
  205. @a=(
  206.  "AvantGarde-Book",
  207.  "AvantGarde-Demi",
  208.  "AvantGarde-BookOblique",
  209.  "AvantGarde-DemiOblique");
  210. @b=(
  211.  "Bookman-Light",
  212.  "Bookman-Demi",
  213.  "Bookman-LightItalic",
  214.  "Bookman-DemiItalic");
  215.  
  216. # Below is an example how to add a new font, specified on the command line
  217. # with "-f myf". Remove the "#" characters and change the names into the
  218. # appropriate for your font. Be sure that you get the names of the different
  219. # styles right. You should also add the name ("myf" in this example) to the
  220. # list of fonts on the line "$pfonts="Possible choices..." below the example.
  221.  
  222. #@myf=(
  223. # "MyFont",
  224. # "MyFont-Bold",
  225. # "MyFont-Italic",
  226. # "MyFont-BoldItalic");
  227.  
  228. $pfonts="Possible choices are: n, t, h, hn, p, a and b";
  229. $nf=eval "\$$opt_f\[0]" || die "Unknown font: $opt_f\n$pfonts\n";
  230. $bf=eval "\$$opt_f\[1]";
  231. $if=eval "\$$opt_f\[2]";
  232. $bi=eval "\$$opt_f\[3]";
  233.  
  234. %style=("n",1, "f",2, "b",3, "fb",4, "i",5, "fi",6, "bi",7, "fbi",8);
  235. for $i (1..6) {
  236.   $temp=eval "\$opt_t$i";
  237.   die "Unknown font style: $temp\n$styles\n" if !$style{$temp};
  238.   eval "\$t$i=$style{$temp}-1"
  239. }
  240.  
  241. %latin1=(
  242. "AElig",306,
  243. "Aacute",301,
  244. "Acirc",302,
  245. "Agrave",300,
  246. "Aring",305,
  247. "Atilde",303,
  248. "Auml",304,
  249. "Ccedil",307,
  250. "ETH",320,
  251. "Eacute",311,
  252. "Ecirc",312,
  253. "Egrave",310,
  254. "Euml",313,
  255. "Iacute",315,
  256. "Icirc",316,
  257. "Igrave",314,
  258. "Iuml",317,
  259. "Ntilde",321,
  260. "Oacute",323,
  261. "Ocirc",324,
  262. "Ograve",322,
  263. "Oslash",330,
  264. "Otilde",325,
  265. "Ouml",326,
  266. "THORN",336,
  267. "Uacute",332,
  268. "Ucirc",333,
  269. "Ugrave",331,
  270. "Uuml",334,
  271. "Yacute",335,
  272. "aacute",341,
  273. "acirc",342,
  274. "aelig",346,
  275. "agrave",340,
  276. "aring",345,
  277. "atilde",343,
  278. "auml",344,
  279. "ccedil",347,
  280. "eacute",351,
  281. "ecirc",352,
  282. "egrave",350,
  283. "eth",360,
  284. "euml",353,
  285. "iacute",355,
  286. "icirc",356,
  287. "igrave",354,
  288. "iuml",357,
  289. "ntilde",361,
  290. "oacute",363,
  291. "ocirc",364,
  292. "ograve",362,
  293. "oslash",370,
  294. "otilde",365,
  295. "ouml",366,
  296. "szlig",337,
  297. "thorn",376,
  298. "uacute",372,
  299. "ucirc",373,
  300. "ugrave",371,
  301. "uuml",374,
  302. "yacute",375,
  303. "yuml",377,
  304. "copy",251,
  305. "reg",256,
  306. "nbsp",240);
  307.  
  308. undef $/;
  309.  
  310. if($html=~m|://| || $html=~/^news:/) {
  311.   &gethtml;
  312.   unless(($ba2)=$html=~m|(.*://.*/)|) {$ba2=$html."/"}
  313. } elsif ($html) {
  314.   open(FILE,$html);
  315.   $_=<FILE>;
  316.   close FILE;
  317. } else {
  318.   $_=<>
  319. }
  320.  
  321. s|\r||g;
  322. for ($opt_IM,$opt_zl,$opt_zr) {
  323.   s|\\|\\200|g;
  324.   s|\(|\\201|g;
  325.   s|\)|\\202|g;
  326. }
  327.  
  328. $P1=<<EOC; 
  329. %!
  330. %%Title: @ARGV
  331. %%DocumentFonts: $nf $bf $if $bi $ff $fb $fi $ft
  332. %%Creator: $version, written by Jan Karrman, jan\@tdb.uu.se
  333. %%EndComments
  334. save
  335. 1000 dict begin
  336. /D {def} def
  337. /t {true} D
  338. /f {false} D
  339. /RF {/$nf} D
  340. /BF {/$bf} D
  341. /IF {/$if} D
  342. /IB {/$bi} D
  343. /FF {/$ff} D
  344. /FB {/$fb} D
  345. /FI {/$fi} D
  346. /FT {/$ft} D
  347. /F $opt_s D
  348. /W {$w F div} D
  349. /LE {$l F div} D
  350. /PS $opt_p D
  351. /HS [$h1 $h2 $h3 $h4 $h5 $h6] D
  352. /HT [$t1 $t2 $t3 $t4 $t5 $t6] D
  353. /MK $mask D
  354. /NO $number D
  355. /ZL $lfoot D
  356. /ZR $rfoot D
  357. /Zl ($opt_zl) D
  358. /Zr ($opt_zr) D
  359. /TU $twoup D
  360. /AU $ulanch D
  361. /SN $opt_N D
  362. /LA {TU PM 1 eq and {W $mm F div add 0 translate}
  363.  {$xc $yc translate$rot F dup scale} ie$fr} D
  364. /FP $opt_B D
  365. /SG [$is $opt_i $msc] D
  366. $dupl
  367. %-- End of variable part --
  368. EOC
  369.  
  370. if(/^%!/ && /%-- End of variable part --/) {
  371.   &openps if ($opt_o);
  372.   print $P1.$';
  373.   for $s ("b","C","c","cw","g","t") {
  374.     print STDERR "Option -$s ignored\n" if(eval "\$opt_$s");
  375.   }
  376.   exit
  377. }
  378.  
  379. if($opt_c || $opt_C || $opt_cw) {
  380.   $opt_cw="weblint" unless $opt_cw;
  381.   $file=$html;
  382.   if($html=~m|://|) {
  383.     open(SCRATCH,">$scr");
  384.     print SCRATCH;
  385.     close SCRATCH;
  386.     $file="$scr";
  387.   }
  388.   print STDERR `$opt_cw $file`;
  389.   exit if($opt_C);
  390. }
  391.  
  392. for $tag ("head","title") {
  393.   if(m|</$tag>|i) {
  394.     $head=$`;
  395.     $body=$';
  396.     if($head=~/<plaintext|<xmp|<listing/i) {
  397.       $head="";
  398.       $body=$_
  399.     }
  400.     $_=$body
  401.   }
  402. }
  403.  
  404. $b2=$opt_b;
  405. unless($b2) {
  406.   ($b2)=$head=~/<base[ \n]+href *= *"([^"]*)"[^>]*>/i;
  407.   unless($b2) {($b2)=$head=~/<base[ \n]+href *= *([\w\.-]+)[^>]*>/i}
  408.   unless($b2) {$b2=$ba2}
  409. }
  410. $b2=~s|[^/]*$||;
  411. ($b1)=$b2=~m|(.*://[^/]*)/|;
  412.  
  413. $P1.=<<EOT;
  414. /ie {ifelse} D
  415. /E {exch} D
  416. /M {moveto} D
  417. /S {show} D
  418. /R {rmoveto} D
  419. /L {lineto} D
  420. /RL {rlineto} D
  421. /CP {currentpoint} D
  422. /SW {stringwidth} D
  423. /GI {getinterval} D
  424. /PI {putinterval} D
  425. /U {gsave CP currentfont /FontInfo get /UnderlinePosition get
  426.  0 E currentfont /FontMatrix get dtransform E pop add newpath M
  427.  dup SW RL stroke grestore} D
  428. /B {-10 3 R gsave CP newpath 2.5 0 360 arc closepath
  429.  UI 2 mod 0 eq {stroke} {fill} ie grestore 10 -3 R} D
  430. /NP {/PM PN SN sub 2 mod D PN SN gt TU not PM 0 eq or and {showpage} if
  431.  0.6 setlinewidth LA /BP t D /PN PN 1 add D
  432.  /OF currentfont D RF findfont 10 scalefont setfont
  433.  /YO {LE neg 60 F div dup 40 gt {pop 40} if sub} D
  434.  NO {W 2 div YO M PN ST cvs S} if
  435.  ZL {0 YO M Zl S} if
  436.  ZR {W YO M Zr dup stringwidth pop neg 0 R S} if
  437.  OF setfont
  438.  XO SZ SL get neg M /CI 0 D} D
  439. /SF {/CS E D CS SZ SL 3 2 roll put /YI CS -1.2 mul D dup ST cvs C1 E join
  440.  ( NF ) join /C1 E D NF /BW ( ) SW pop D} D
  441. /NF {FL E get findfont CS scalefont setfont} D
  442. /FS {CF MK PF {1 or} if and or /CF E D FR SL CF put CF E SF} D
  443. /FL [RF FF BF FB IF FI IB FT] D
  444. /reencodeISO {
  445. dup dup findfont dup length dict begin
  446. { 1 index /FID ne { def }{ pop pop } ie } forall
  447. /Encoding ISOLatin1Encoding D
  448. currentdict end definefont
  449. } D
  450. /ISOLatin1Encoding [
  451. /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  452. /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  453. /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  454. /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  455. /space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright
  456. /parenleft/parenright/asterisk/plus/comma/minus/period/slash
  457. /zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon
  458. /less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N
  459. /O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright
  460. /asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m
  461. /n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde
  462. /.notdef/backslash/parenleft/parenright/.notdef/.notdef/.notdef/.notdef
  463. /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  464. /.notdef/dotlessi/grave/acute/circumflex/tilde/macron/breve
  465. /dotaccent/dieresis/.notdef/ring/cedilla/.notdef/hungarumlaut
  466. /ogonek/caron/space/exclamdown/cent/sterling/currency/yen/brokenbar
  467. /section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot
  468. /hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior
  469. /acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine
  470. /guillemotright/onequarter/onehalf/threequarters/questiondown
  471. /Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla
  472. /Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
  473. /Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
  474. /multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute
  475. /Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis
  476. /aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave
  477. /iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex
  478. /otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis
  479. /yacute/thorn/ydieresis
  480. ] D
  481. FL {reencodeISO D} forall
  482.  
  483. /BS {/PC E D /TX E D /fin f D /CW 0 D /LK 0 D /SC 0 D
  484.  /RT TX D {RT ( ) search {/NW E D pop /RT E D /WH NW SW pop D CW WH add LL gt
  485.  {TX SC LK SC sub GI PC /SC LK D /CW WH BW add D}
  486.  {/CW CW WH add BW add D} ie
  487.  /LK LK NW length add 1 add D} {pop exit} ie} loop
  488.  /fin t D /LC TX length D /WH RT SW pop D CW WH add LL gt
  489.  {TX SC LK SC sub GI PC NL RT dup () ne {PC} {pop} ie}
  490.  {TX SC LC SC sub GI PC} ie} D
  491.  
  492. /BT {RS dup dup () ne E ( ) ne and
  493.  {/LS LL D /LL W L1 sub XO sub D {/CI 0 D SH /BP f D fin not {NL} if
  494.   /HM t D /LL LS D} BS} {BG {pop} {SH /BP f D} ie} ie} D
  495. /BL {HM not {CP E pop XO E M} if} D
  496. /NL {BL W XO sub L1 sub TB {BW add} if AT mul 2 div YA neg dup 0 lt {3 sub} if
  497.  R F0 CF ne {F0 NF} if C1 cvx exec /C1 () D /L1 0 D /F0 CF D
  498.  BP not {0 YB NN neg R} if /YA 0 D /YB 0 D CP /YC E D pop XO YC M YC LE neg gt
  499.  {YI CI sub dup 0 lt BP not and {dup 0 E R CI add /CI E D} {pop} ie}
  500.  {NP} ie /T t D} D
  501. /RS {/TM E D /CN 0 D TM
  502.  {dup 9 eq E 10 eq or {TM CN ( ) PI} if
  503.   /CN CN 1 add D} forall /CN 0 D /BK HM EN and {0} {1} ie D TM
  504.  {dup 32 ne {TM CN 3 2 roll put /CN CN 1 add D /BK 0 D}
  505.  {pop BK 0 eq {TM CN 32 put /CN CN 1 add D} if /BK 1 D} ie}
  506.   forall TM 0 CN GI dup dup () ne E ( ) ne and
  507.   {dup CN 1 sub get 32 eq {/EN f D} {/EN t D} ie} if} D
  508. /join {2 copy length E length add string dup 4 2 roll 2 index 0 3 index
  509.  PI E length E PI} bind D
  510. /EG {dup 0 E dup () eq {E pop} {E get} ifelse 10 ne {(\\n) E join} if} D
  511. /WR {PB {EG /PB f D} if PP {EG /PP f D} if (\\n) search
  512.  {dup () ne BP not or {TR /CI 0 D /NC 0 D NL pop WR}{pop pop WR} ie} {TR} ie} D
  513. /TR {(\\t) search {dup length /NC E NC add D SH MS 0 8 NC 8 mod sub dup
  514.  /NC E NC add D GI SH pop TR} {dup length /NC E NC add D SH} ie
  515.  /BP f D} D
  516. /SH {CP E pop LE neg lt {NP} if dup SW pop L1 add /L1 E D
  517.  C1 (\\() join T not {( ) join} if E join (\\)) join
  518.  AU AF and UF or {( U ) join} if ( S ) join /C1 E D /T t D /TB EN not D} D
  519. /BG {CP pop XO sub abs 0.01 lt} D
  520. /ON {AR AI NN get 1 add dup AR AI 3 -1 roll put ST cvs length dup ST E (. ) PI
  521.  ST 0 3 -1 roll 2 add GI dup SW pop neg 0 R S} D
  522. /SP {YI E /YI E D NL /YI E D} D
  523. /BR {BN} D
  524. /BN {PF {WR} {BT NL} ie /HM f D} D
  525. /AB {CH E 0 E put CH join WB} D
  526. /NN {dup 0 lt {pop 0} if} D
  527. /H  {1 sub /HL E D E BN /AT E D CP E pop LE neg WW add lt {NP} if
  528.  BH SP /SL SL 1 add D HS HL get HT HL get FS} D
  529. /EH {BN /AT 0 D AH SP /SL SL 1 sub NN D /CF 0 D SZ SL get FR SL get FS} D
  530. /P  {E PF {WR /PP t D} {BN AE not {AH SP} if} ie /AT E D} D
  531. /HR {BN 0 CP E pop M gsave PF {0 YI R} if W 0 RL stroke grestore /CI 0 D
  532.  /BP f D NL} D
  533. /AD {BN /AE t D AH SP 4 11 SF} D
  534. /DA {BN /AE f D AH SP 0 11 SF} D
  535. /PR {BN /AT 0 D /CF 0 D 9 PS mul 1 FS /PF t D /PB t D /NC 0 D} D
  536. /PW {pop PR} D
  537. /RP {PF {dup () ne {dup dup length 1 sub get 10 ne {(\\n) join} if} if
  538.  WR AH SP /CF 0 D 11 0 FS /PF f D} {BT} ie} D
  539. /SI {/XO AI LG add NN IN mul BC NN BI mul add D /LL W XO sub D} D
  540. /DT {BN /LG LG 1 sub D SI /LG LG 1 add D BL} D
  541. /DD {BN SI BL} D
  542. /DL {BN XO 0 eq {AH SP} if /LG LG 1 add D BL} D
  543. /LD {BN LG 0 gt {/LG LG 1 sub D} if SI XO 0 eq {AH SP} if BL} D
  544. /UL {BN XO 0 eq {AH SP} {NL} ie NR AI NN 0 put /UI UI 1 add D
  545.  /AI AI 1 add D SI BL} D
  546. /LU {BN /UI UI 1 sub D /AI AI 1 sub D SI XO 0 eq {AH SP} {NL} ie BL} D
  547. /OL {BN XO 0 eq {AH SP} {NL} ie NR AI NN 1 put /AI AI 1 add D SI BL} D
  548. /LO {BN AR AI NN 0 put /AI AI 1 sub D SI XO 0 eq {AH SP} {NL} ie BL} D
  549. /LI {BN /BP f D /CI 0 D CP E pop LE neg lt {NP} if
  550.  /C1 C1 NR AI 1 sub NN get 1 eq {( ON )} {( B )} ie join D BL} D
  551. /BQ {BN AH SP /BC BC 1 add D SI BL} D
  552. /QB {BN AH SP /BC BC 1 sub D SI BL} D
  553. /WB {PF {WR} {BT} ie} D
  554. /A  {WB /AF t D} D
  555. /EA {WB /AF f D} D
  556. /SS {SZ SL get /SL SL 1 add D} D
  557. /I  {WB SS 4 FS} D
  558. /BD {WB SS 2 FS} D
  559. /TT {WB SS 1 FS} D
  560. /KB {WB SS /CF 0 D 3 FS} D
  561. /CT {WB SS /CF 0 D 4 FS} D
  562. /SM {WB SS /CF 0 D 1 FS} D
  563. /ES {WB /SL SL 1 sub NN D /CF 0 D SZ SL get FR SL get FS} D
  564. /UN {WB /UF t D} D
  565. /NU {WB /UF f D} D
  566. /SB {0 1 NI {/N E D /K WS N get D /NY AY N get FC N get mul D /BV NY array D
  567.  0 1 NY 1 sub {/TM K string D currentfile TM readhexstring pop pop BV E TM put}
  568.  for BM N BV put} for} D
  569. /colorimage where {pop} {
  570.  /colorimage {
  571.   pop pop /Bp E D /Gp E D /Rp E D
  572.   {/Re Rp D /Gr Gp D /Bl Bp D
  573.   0 1 Re length 1 sub {
  574.    /i E D Gr i Re i get 0.299 mul Gr i get 0.587 mul add Bl i get 0.114 mul add
  575.    cvi put
  576.   } for Gr} image
  577.  } D
  578. } ie
  579. /IP {BV N get /N N 1 add D} D
  580. /II {/K E D /TY E D /XW AX K get D /YW AY K get D /IS SG IT K get get D
  581.  /XS XW IS mul D /YS YW IS mul D YS CS sub TY 2 eq {/MB E D /MA 0 D}
  582.  {TY 2 mod 1 eq {2 div /MA E 2 sub D /MB MA 4 add D}{/MA E D /MB 0 D} ie} ie} D
  583. /IM {II /ty TY D /xs XS D /ys YS D /ya YA D /yb YB D /ma MA D /mb MB D /k K D
  584.  /CI 0 D WB L1 xs add dup /L1 E D XO add W gt
  585.  {NL /YA ma D /YB mb D /YS ys D /L1 xs D}
  586.  {ma YA gt {/YA ma D} if mb YB gt {/YB mb D} if} ie CP E pop YS sub LE neg lt
  587.  {NP /YA ma D /YB mb D /L1 xs D} if /BP f D ty ST cvs ( ) join k ST cvs join
  588.  C1 E join ( DI ) join FP 2 eq FP 1 eq AF and or {( FM ) join} if /C1 E D
  589.  /HM t D /EN f D /T TY 3 eq D} D
  590. /DI {II /YN YW neg D /HM t D /CI 0 D /K2 IX K get D gsave CP MB sub translate
  591.  K2 0 ge {/DP AZ K2 get D /BV BM K2 get D XS YS scale /N 0 D XW YW DP
  592.  [XW 0 0 YN 0 YW] {IP} FC K2 get 1 eq {image} {{IP} {IP} t 3 colorimage} ie}
  593.  {PV K2 neg 1 sub get exec} ie grestore XS 0 R} D
  594. /FM {gsave CP MB sub translate XS neg 0 M 0 YS RL XS 0 RL 0 YS neg RL XS neg
  595.  0 RL stroke grestore} D
  596. /BH -35 D
  597. /AH -28 D
  598. /LL W D
  599. /XO 0 D
  600. /YI 0 D
  601. /CI 0 D
  602. /LG 0 D
  603. /AI 0 D
  604. /UI 0 D
  605. /IN 30 D
  606. /BI 12 D
  607. /WW 50 D
  608. /AR [0 0 0 0 0 0 0 0 0 0] D
  609. /NR [0 0 0 0 0 0 0 0 0 0] D
  610. /FR [0 0 0 0 0 0 0 0 0 0] D
  611. /SZ [0 0 0 0 0 0 0 0 0 0] D
  612. /SL 0 D
  613. /CF 0 D
  614. /BC 0 D
  615. /YA 0 D
  616. /YB 0 D
  617. /F0 0 D
  618. /N 0 D
  619. /AT 0 D
  620. /C1 () D
  621. /C2 () D
  622. /L1 0 D
  623. /L2 0 D
  624. /PN SN D
  625. /MS (        ) D
  626. /CH 1 string D
  627. /ST 6 string D
  628. /HM f D
  629. /PF f D
  630. /EN f D
  631. /TB f D
  632. /UF f D
  633. /PP f D
  634. /AE f D
  635. /AF f D
  636. /BP t D
  637. /T t D
  638. EOT
  639.  
  640. $nimg=-1;
  641. $nbm=-1;
  642. s|\r||g;
  643. s|\\|\\200|g;
  644. s|\(|\\201|g;
  645. s|\)|\\202|g;
  646. &openps if ($opt_o);
  647.  
  648. #  Yes, I know Perl has case-insensitive pattern matching. But on my system
  649. #  it takes about 10 times longer to run!
  650.  
  651. if(/<[pP][lL][aA][iI][nN][tT][eE][xX][tT] *>/) {$_=$`;$pt=$'};
  652. while($_){
  653.   if(/(<[lL][iI][sS][tT][iI][nN][gG] *>)/) {$_=$`; $tag=$1; $rest=$';
  654.     if(/<[xX][mM][pP] *>/) {$_=$`; &Subst; $P2.=")XX("; $_=$'.$tag.$rest;
  655.       if(m|</[xX][mM][pP] *>|) {$P2.="$`)RP("; $_=$'}
  656.       else {$P2.=$'; $_=""}}
  657.     else {&Subst; $P2.=")XX("; $_=$rest;
  658.       if(m|</[lL][iI][sS][tT][iI][nN][gG] *>|) {$P2.="$`)RP("; $_=$'}
  659.       else {$P2.=$'; $_=""}}}
  660.   elsif(/<[xX][mM][pP] *>/) {$_=$`; &Subst; $P2.=")XX("; $_=$';
  661.     if(m|</[xX][mM][pP] *>|) {$P2.="$`)RP("; $_=$'}
  662.     else {$P2.=$'; $_=""}}
  663.   else {&Subst;$_=""}
  664. }
  665. if($pt) {$P2.=")XX($pt"};
  666. $P2.=")";
  667. while($P2=~/XX\(([^)]*)\)/) {
  668.   $beg=$`;
  669.   $mat=$1;
  670.   $end=$';
  671.   $mat=~s/(.*\n){30}.*/$&)WR(/g;
  672.   $P2=$beg."PR(".$mat.")".$end;
  673. }
  674.  
  675. print $P1;
  676. if($nimg>=0) {
  677.   print "/AX [".join(' ',@XS)."] D\n";
  678.   print "/AY [".join(' ',@YS)."] D\n";
  679.   print "/IX [".join(' ',@IX)."] D\n";
  680.   print "/IT [".join(' ',@IT)."] D\n";
  681.   if($nbm>=0) {
  682.     print "/AZ [".join(' ',@DP)."] D\n";
  683.     print "/WS [".join(' ',@WS)."] D\n";
  684.     print "/FC [".join(' ',@FC)."] D\n";
  685.     print "/NI $nbm D\n";
  686.     print "/BM ",$nbm+1," array D\n%%EndProlog\nSB\n";
  687.     for $i (0..$nbm) {print "$BM[$i]\n"}
  688.   }
  689.   if($nps) {
  690.     print "/PV [".join("\n",@PS)."] D\n";
  691.   }
  692. }
  693. print <<EOP;
  694. 0 11 SF
  695. 0 LE neg 20 sub M
  696. (
  697. EOP
  698. print $P2."WB NL showpage end restore\n";
  699. unlink <$scr*>;
  700. exit;
  701.  
  702. sub Subst{
  703.   s|<!--NewPage-->|)WB NL NP(|g;
  704.   while (/<!--/) {
  705.     $beg=$`;
  706.     if(/--[ \t\n]*>/) {
  707.       $_=$beg.$';
  708.     } else {
  709.       $_=$beg;
  710.     }
  711.   }
  712.   s|</[pP][rR][eE] *>[ \n]*<[pP][rR][eE]>||g;
  713.   s|</?[pP]>[ \n]*<[pP][rR][eE]>|)XX(|g;
  714.   s|<[lL][iI]>[ \n]*<[pP]>|)0 P()LI(|g;
  715.   s|<[hH]([1-6])[ \n]+[aA][lL][iI][gG][nN] *= *['"]?[cC][eE][nN][tT][eE][rR][^>]*>|)1 $1 H(|g;
  716.   s|<[hH]([1-6])[ \n]+[aA][lL][iI][gG][nN] *= *['"]?[rR][iI][gG][hH][tT][^>]*>|)2 $1 H(|g;
  717.   s|<[hH]([1-6]) *[^>]*>|)0 $1 H(|g;
  718.   s|</[hH][1-6]>|)EH(|g;
  719.   s|<[bB][rR][^>]*>|)BR(|g;
  720.   s|<[pP]>|)0 P(|g;
  721.   s|<[pP][ \n]+[aA][lL][iI][gG][nN] *= *['"]?[cC][eE][nN][tT][eE][rR][^>]*>|)1 P(|g;
  722.   s|<[pP][ \n]+[aA][lL][iI][gG][nN] *= *['"]?[rR][iI][gG][hH][tT][^>]*>|)2 P(|g;
  723.   s|<[pP][ \n]+[^>]*>|)0 P(|g;
  724.   s|</[pP]>|)0 P(|g;
  725.   s|<[hH][rR][^>]*>|)HR(|g;
  726.   s|<[aA][dD][dD][rR][eE][sS][sS] *>|)AD(|g;
  727.   s|</[aA][dD][dD][rR][eE][sS][sS]>|)DA(|g;
  728.   s|<[pP][rR][eE] *>|)XX(|g;
  729.   s|<[pP][rR][eE] *[wW][iI][dD][tT][hH] *= *['"]* *(\d+) *['"]* *>|)$1 PW(|g;
  730.   s|</[pP][rR][eE]>|)RP(|g;
  731.   s|<[dD][tT] *>|)DT(|g;
  732.   s|<[dD][dD] *>|)DD(|g;
  733.   s|<[dD][lL][^>]*>|)DL(|g;
  734.   s|</[dD][lL]>|)LD(|g;
  735.   s|<[uU][lL][^>]*>|)UL(|g;
  736.   s|</[uU][lL]>|)LU(|g;
  737.   s|<[mM][eE][nN][uU] *>|)UL(|g;
  738.   s|</[mM][eE][nN][uU]>|)LU(|g;
  739.   s|<[dD][iI][rR] *>|)UL(|g;
  740.   s|</[dD][iI][rR]>|)LU(|g;
  741.   s|<[oO][lL] *[^>]*>|)OL(|g;
  742.   s|</[oO][lL]>|)LO(|g;
  743.   s|<[lL][iI] *>|)LI(|g;
  744.   s|</[lL][iI] *>||g;
  745.   s|<[bB][lL][oO][cC][kK][qQ][uU][oO][tT][eE] *>|)BQ(|g;
  746.   s|</[bB][lL][oO][cC][kK][qQ][uU][oO][tT][eE]>|)QB(|g;
  747.   s|<[sS][tT][rR][oO][nN][gG] *>|)BD(|g;
  748.   s|</[sS][tT][rR][oO][nN][gG]>|)ES(|g;
  749.   s|<[sS][aA][mM][pP] *>|)SM(|g;
  750.   s|</[sS][aA][mM][pP]>|)ES(|g;
  751.   s|<[cC][iI][tT][eE] *>|)CT(|g;
  752.   s|</[cC][iI][tT][eE]>|)ES(|g;
  753.   s|<[vV][aA][rR] *>|)I(|g;
  754.   s|</[vV][aA][rR]>|)ES(|g;
  755.   s|<[bB] *>|)BD(|g;
  756.   s|</[bB]>|)ES(|g;
  757.   s|<[iI] *>|)I(|g;
  758.   s|</[iI]>|)ES(|g;
  759.   s|<[tT][tT] *>|)TT(|g;
  760.   s|</[tT][tT]>|)ES(|g;
  761.   s|<[uU] *>|)UN(|g;
  762.   s|</[uU]>|)NU(|g;
  763.   s|<[dD][fF][nN] *>|)I(|g;
  764.   s|</[dD][fF][nN]>|)ES(|g;
  765.   s|<[eE][mM] *>|)I(|g;
  766.   s|</[eE][mM]>|)ES(|g;
  767.   s|<[cC][oO][dD][eE] *>|)SM(|g;
  768.   s|</[cC][oO][dD][eE]>|)ES(|g;
  769.   s|<[kK][bB][dD] *>|)KB(|g;
  770.   s|</[kK][bB][dD]>|)ES(|g;
  771.   s|<[aA][ \n]+[^>]*[hH][rR][eE][fF][^>]*>|)A(|g;
  772.   s|</[aA]>|)EA(|g;
  773.   for $char (keys %latin1) {s|&$char;?|\\$latin1{$char}|g}
  774.  
  775.   while (/<([iI][mM][gG]|[fF][iI][gG])[ \n]/) {
  776.     $beg=$`;
  777.     $'=~/>/;
  778.     $img=$`;
  779.     $end=$';
  780.     $img=~s/\n/ /g;
  781.     if($opt_T) {
  782.       &getalt
  783.     } else {
  784.       $al=0;
  785.       ($align)=$img=~/align *= *['"]?(\w*)/i;
  786.       if($align=~/^middle$/i) {$al=1};
  787.       if($align=~/^top$/i) {$al=2};
  788.       ($url)=$img=~/src *= *"([^"]*)"/i;
  789.       unless ($url) {($url)=$img=~m|src *= *([\w\.\-:/~%]+)|i};
  790.       ($url)=$url=~/([^ \n]*)/;
  791.       print STDERR "\nImage: $url\n" if($opt_X);
  792.       $URL=$url;
  793.       $text=$cmd{$url};
  794.       unless ($text) {
  795.         if(!$url || $failed{$url}) {
  796.           &getalt
  797.         } else {
  798.           unless($url=~m|://|) {
  799.             if($url=~m|^http:(.*)|) {$url=$1}
  800.             if($url=~m|^/|) {$URL=$b1.$url} else {$URL=$b2.$url}
  801.           }
  802.           print STDERR "Expanded to: $URL\n" if($opt_X);
  803.           &pictops;
  804.           if($bm || $ps) {
  805.             print STDERR "Size: ".$xs."x".$ys."\n" if($opt_X);
  806.             $nimg++;
  807.             push (@XS,$xs);
  808.             push (@YS,$ys);
  809.             if($bm) {
  810.               $nbm++;
  811.               push (@DP,$dp);
  812.               push (@BM,$bm);
  813.               push (@WS,int(($xs-1)*$dp/8)+1);
  814.               push (@FC,$fc);
  815.               push (@IX,$nbm);
  816.               push (@IT,0);
  817.             }
  818.             if($ps) {
  819.               $nps--;
  820.               push (@IX,$nps);
  821.               push (@PS,$ps);
  822.               push (@IT,1);
  823.             }
  824.             $text=" $nimg IM(";
  825.             $cmd{"$url"}=$text;
  826.           } else {
  827.             &getalt;
  828.             $failed{"$url"}=1;
  829.           }
  830.         }
  831.       }
  832.     }
  833.     if($cmd{$url}) {$text=")".$al.$text}
  834.     $_=$beg.$text.$end
  835.   }
  836.   if(/<[mM][aA][tT][hH]/) {chdir $tmpdir || die "Cannot cd to $tmpdir\n"};
  837.   while (/<[mM][aA][tT][hH]/) {
  838.     $beg=$`;
  839.     $rest=$&.$';
  840.     $rest=~m|</[mM][aA][tT][hH]>|;
  841.     $end=$';
  842.     $math=$`;
  843.     $math=~s|\\200|\\|g;
  844.     $math=~s|\\201|\(|g;
  845.     $math=~s|\\202|\)|g;
  846.     &math2tex($math);
  847.     open(SCRATCH,">$scr.tex");
  848.     print SCRATCH $tex;
  849.     close SCRATCH;
  850.     unlink $scr.ps;
  851.     `echo r|tex $scr.tex;dvips -E $scr.dvi`;
  852.     open(PS,"$scr.ps");
  853.     $pic=<PS>;
  854.     if($pic=~/^%!/ && $pic=~/%%BoundingBox: +($F) +($F) +($F) +($F)/) {
  855.       $xs=$3-$1;
  856.       $ys=$4-$2;
  857.       $ps="{save\n0 0 M 1 F div dup scale /showpage {} D -$1 -$2 translate\n";
  858.       for $i (split(/\n/,$pic)) {
  859.         $ps.=$i."\n" if($i && $i!~/^%/)
  860.       }
  861.     }
  862.     $ps.="restore}\n";
  863.     $nimg++;
  864.     $nps--;
  865.     push (@XS,$xs);
  866.     push (@YS,$ys);
  867.     push (@IX,$nps);
  868.     push (@PS,$ps);
  869.     push (@IT,2);
  870.     $_=$beg.")3 $nimg IM(".$end;
  871.   }
  872.   s|<[^ >][^>]*>||g;
  873.   s|<?|<|g;
  874.   s|>?|>|g;
  875.   s|"?|"|g;
  876.   s|&#(\d+);?|)$1 AB(|g;
  877.   s|&?|\&|g;
  878.   $P2.=$_
  879. }
  880. sub math2tex {
  881.   local($_)=@_;
  882.   local($beg,$rest);
  883.   %a=("line","overline",
  884.   "cub","overbrace",
  885.   "hat","widehat",
  886.   "tilde","widetilde",
  887.   "larr", "overleftarrow",
  888.   "rarr", "overrightarrow");
  889.   %b=("line","underline",
  890.   "cub","underbrace",
  891.   "hat","widehat",
  892.   "tilde","widetilde");
  893.   %s=("medium","\\big",
  894.   "large","\\Big",
  895.   "huge","\\bigg");
  896.   $st='\rm' if(/<math[ \n\t]+class[ \n\t]*=[ \n\t]*["']?chem["']?[ \n\t]*>/i);
  897.   s/<math[^>]*>//gi;
  898.   s/__/_\\>_/gi;
  899.   s/\^\^/^\\>^/gi;
  900.   s/_([^_]+)_/_{$1}/g;
  901.   s/\^([^^]+)\^/^{$1}/g;
  902.   s/ ?/\\,/gi;
  903.   s/&sp;?/\\>/gi;
  904.   s/ ?/\\;/gi;
  905.   s/\\240/\\>/gi;
  906.   s/&vepsilon;?/\\varepsilon /gi;
  907.   s/&vtheta;?/\\vartheta /gi;
  908.   s/ο?/o/gi;
  909.   s/&vsigma;?/\\varsigma /gi;
  910.   s/&inf;?/\\infty /gi;
  911.   s/∫?/\\int\\limits /gi;
  912.   s/∑?/\\sum\\limits /gi;
  913.   s/∏?/\\prod\\limits /gi;
  914.   s/→?([_^])/\\mathop\\rightarrow\\limits$1 /gi;
  915.   s/→?/\\rightarrow /gi;
  916.   s/&pd;?/\\partial /gi;
  917.   s/<t>/\\hbox{/gi;
  918.   s/<b>/\\bf /gi;
  919.   s/<bt>/\\bf\\hbox{/gi;
  920.   s/<sub[^>]*>/_{/gi;
  921.   s/<sup[^>]*>/\^{/gi;
  922.   s/<box[ \n\t]*size=["']?(\w+)["']?>/{\\def\\lft{$s{$1}}\\def\\rgt{$s{$1}}/gi;
  923.   s/<box[^>]*>/{/gi;
  924.   s/<text[ \t\n]*>/\\hbox{/gi;
  925.   s/([\(\[\|]) *<left>/\\lft$1/gi;
  926.   s/<right>/\\rgt /gi;
  927.   s/<(atop|choose|over)>/\\\L$1 /gi;
  928.   s/<of>/}\\of{/gi;
  929.   s/<bar>/\\overline{/gi;
  930.   s/<vec>/\\overrightarrow{/gi;
  931.   s/<hat>/\\widehat{/gi;
  932.   s/<tilde>/\\widetilde{/gi;
  933.   s/<(sqrt|root|vec|dot|ddot|hat|tilde)>/\\\L$1\{/gi;
  934.   while(/<above[ \t\n]+sym[ \t\n]*=[ \t\n]*["']?equals["']?[ \t\n]*>/i) {
  935.     $beg=$`."\\overline{\\overline{";
  936.     $rest=$';
  937.     $rest=~s/<\/above>/}}/i;
  938.     $_=$beg.$rest;
  939.   }    
  940.   s/<above[ \t\n]*>/\\overline{/gi;
  941.   s/<above[ \t\n]+sym[ \t\n]*=[ \t\n]*["']?(\w+)["']?[ \t\n]*>/\\$a{$1}\{/gi;
  942.   s/<below[ \t\n]*>/\\underline{/gi;
  943.   s/<below[ \t\n]+sym[ \t\n]*=[ \t\n]*["']?(\w+)["']?[ \t\n]*>/\\$b{$1}\{/gi;
  944.   s/<\/(math|row|item|b)>//gi;
  945.   s/<\/(box|t|bt|sup|sub|sqrt|root|vec|bar|dot|ddot|hat|tilde|above|below|text|array)>/}/gi;
  946.   s/<?/< /gi;
  947.   s/>?/>/gi;
  948.   s/&(\w+);?/\\$1 /gi;
  949.   s/<array[^>]*>/\\matrix{/gi;
  950.   s/<row>[ \t\n]*<item[^>]*>//i;
  951.   s/<row>[ \t\n]*<item[^>]*>/\\cr /gi;
  952.   s/<item>/&/gi;
  953.   s/<[^ ][^>]*>//gi;
  954.   s/\n*$//;
  955.   $tex="\\magnification=$mag\\nopagenumbers\n\\def\\lft{\\left}"
  956.       ."\\def\\rgt{\\right}\n\$\$$st".$_."\$\$\n\\end\n";
  957. }
  958. sub Getopts {
  959.   local($optlist)=@_;
  960.   local(@args,$_,$opt,$opts,$rest,$olist,$plist,$found,@popts);
  961.   local($errs)=0;
  962.   local($[)=0;
  963.   @args=split( /\|/, $optlist );
  964.   for $opt (@args) {
  965.     if(substr($opt,-1,1) ne ':') {$olist.=$opt}
  966.     else {$plist.=$opt}
  967.   }
  968.   @popts=split(/:/,$plist);
  969.   while(@ARGV && ($_=$ARGV[0]) =~ /^-(.*)/) {
  970.     $opt=$1;
  971.     if($opt =~ /^[$olist]+$/) {
  972.       while ($char=chop $opt) {eval "\$opt_$char=1"}
  973.       shift(@ARGV);
  974.     }
  975.     else {
  976.       $found=0;
  977.       for $opts (@popts) {
  978.         $rest=substr($opt,length($opts));
  979.         if(index($opt,$opts)==0) {
  980.           $found=1;
  981.           shift(@ARGV);
  982.           if(length($rest)==0) {
  983.             ++$errs unless @ARGV;
  984.             $rest=shift(@ARGV)
  985.           }
  986.           eval "\$opt_$opts=\$rest";
  987.           eval "\$set_$opts=1"
  988.         }
  989.       }
  990.       if(!$found) {
  991.         print STDERR "Unknown option: $opt\n";
  992.         ++$errs;
  993.         shift(@ARGV)
  994.       }
  995.     }
  996.   }
  997.   $errs==0
  998. }
  999. sub openps {
  1000.   open(STDOUT,">$opt_o") || die "Error opening $opt_o for output\n"
  1001. }
  1002. sub getalt {
  1003.   $alt="";
  1004.   if($img=~/alt *= *"([^"]*)"/i) {$alt=$1; $match=1}
  1005.   if(!$match && $img=~/alt *= *([\w\.-]+)/i) {$alt=$1; $match=1}
  1006.   unless($match) {$alt=$opt_IM}
  1007.   $text=" $alt )WB("
  1008. }
  1009. sub xbmtops {
  1010.   $fc=1;
  1011.   $dp=1;
  1012.   ($xs,$ys)=$pic=~/^#define.* (\d+)[\w\W\n]*^#define.* (\d+)/;
  1013.   $nd=2*int(($xs+7)/8)*$ys;
  1014.   ($pic)=$pic=~/[^#].* char.*[\w\W\n]*{([\w\W\n]*)}/;
  1015.   $pic=~s/[ ,\n]*0x[ ,]*//g;
  1016.   $pic=~y/01246789bdef/f7bd91e62480/;
  1017.   $bm=unpack("H*", pack("h*",$pic));
  1018. }
  1019. sub pmtops {
  1020.   $pm=~/^P([4-6])/;
  1021.   $maptype=$1;
  1022.   return if(!$maptype);
  1023.   $pm=$';
  1024.   $bm="";
  1025.   $wh="[ \t\r\n]";
  1026.   $nint=3;
  1027.   $dp=8;
  1028.   if($maptype==4) {
  1029.     $nint=2;
  1030.     $dp=1;
  1031.   }
  1032.   undef @num;
  1033.   $found=0;
  1034.   while($pm && $found<$nint) {
  1035.     if($pm=~/^$wh*(\d+)/) {$num[$found]=$1};
  1036.     if($num[$found]) {
  1037.       $found++;
  1038.       $pm=$';
  1039.     } elsif($pm=~/^$wh*#.*\n/) {
  1040.       $pm=$';
  1041.     } else {
  1042.       return;
  1043.     }
  1044.   }
  1045.   ($b)=$pm=~/$wh([\w\W\n]*)/;
  1046.   ($xs,$ys,$bits)=@num;
  1047.   return if($bits>255);
  1048.   $fc=1;
  1049.   if($maptype==6) {
  1050.     $fc=3;
  1051.     $nd=6*$xs*$ys;
  1052.     for $j (0..$ys-1) {
  1053.       $tmp="";
  1054.       @w=split(//,substr($b,3*$xs*$j,3*$xs));
  1055.       for $k (0..2) {
  1056.         for $i (0..$xs-1) {
  1057.           $tmp.=$w[3*$i+$k];
  1058.         }
  1059.       }
  1060.       $bm.=$tmp;
  1061.     }
  1062.     $bm=unpack("H*",$bm);
  1063.   } else {
  1064.     $bm=unpack("H*",$b);
  1065.     if($maptype==4) {
  1066.       $nd=2*int(($xs+7)/8)*$ys;
  1067.       $bm=~y/0123456789abcdef/fedcba9876543210/;
  1068.     } else {
  1069.       $nd=2*$xs*$ys;
  1070.     }
  1071.   }
  1072. }
  1073. sub trans {
  1074.   $next = 13;
  1075.   $temp = ord substr($pic,10,1);
  1076.   if($temp & 0x80) {$next += 3*2**(($temp & 0x07) + 1)} else {return};
  1077.   $byte = ord substr($pic,$next,1);
  1078.   while($byte != 0x3b && $next <= length $pic) {
  1079.     if($byte == 0x21) {
  1080.       if(ord substr($pic,$next+1,1) == 0xf9) {
  1081.         if(ord substr($pic,$next+3,1) & 0x01) {
  1082.           print STDERR "Transparent\n" if($opt_X);
  1083.           $index = ord substr($pic,$next+6,1);
  1084.           substr($pic,3*$index+13,3) = "\377\377\377";
  1085.         }
  1086.         return;
  1087.         $next += 2;
  1088.         &skip;
  1089.       } else {
  1090.         $next += 2;
  1091.         &skip;
  1092.       }
  1093.     } elsif($byte == 0x2c) {
  1094.       $next += 10;
  1095.       $temp = ord substr($pic,$next-1,1);
  1096.       if($temp & 0x80) {$next += 3*2**(($temp & 0x07) + 1)};
  1097.       $next++;
  1098.       &skip;
  1099.     } else {return}
  1100.   }
  1101. }
  1102. sub skip {
  1103.   $byte = ord substr($pic,$next,1);
  1104.   while($byte != 0) {
  1105.     $next += $byte + 1;
  1106.     $byte = ord substr($pic,$next,1);
  1107.   }
  1108.   $next++;
  1109.   $byte = ord substr($pic,$next,1);
  1110. }
  1111. sub run {
  1112.   print STDERR "@_\n" if($opt_X);
  1113.   $pm=`@_`;
  1114. }
  1115. sub gethtml {
  1116.   $_=`$geturl '$html'`;
  1117. }
  1118. sub pictops {
  1119.   if($opt_g) {
  1120.     $fc=1;
  1121.     $pg1="pgm";
  1122.     $pg2="|ppmtopgm"
  1123.   } else {
  1124.     $fc=3;
  1125.     $pg1="ppm";
  1126.     $pg2=""
  1127.     }
  1128.   ($type)=$URL=~/([^\?]+)\??/;
  1129.   ($type)=$type=~/\.(\w+)$/;
  1130.   $bm="";
  1131.   $ps="";
  1132.   $pm="";
  1133.   if($URL=~m|://|) {
  1134.     $pic=`$geturl '$URL'`;
  1135.   } else {
  1136.     $flag=0;
  1137.     if($opt_O) {
  1138.       $orig=$URL;
  1139.       unless($orig=~s/\.\w*$/.ps/) {$orig.=".ps"};
  1140.       if(open(ORIG,"$orig")) {
  1141.         $pic=<ORIG>;
  1142.         close ORIG;
  1143.         if($pic=~/^%!/ && $pic=~/%%BoundingBox:/) {
  1144.           $flag=1;
  1145.           print STDERR "Using $orig as original for $URL\n" if($opt_X);
  1146.         }
  1147.       }
  1148.     }
  1149.     if(!$flag) {
  1150.       open(PIC,"$URL");
  1151.       $pic=<PIC>;
  1152.       close PIC;
  1153.     }
  1154.   }
  1155.   $pic=~s/^[\n\r]*//;
  1156.   &trans if($pic=~/^GIF/);
  1157.   open(SCRATCH,">$scr");
  1158.   print SCRATCH $pic;
  1159.   close SCRATCH;
  1160.   if($pic=~/^%!/ && $pic=~/%%BoundingBox: +($F) +($F) +($F) +($F)/) {
  1161.     $xs=$3-$1;
  1162.     $ys=$4-$2;
  1163.     $ps="{save\n0 0 M\nIS IS scale\n/showpage {} D\n-$1 -$2 translate\n";
  1164.     for $i (split(/\n/,$pic)) {
  1165.       $ps.=$i."\n" if($i && $i!~/^%/)
  1166.     }
  1167.     $ps.="restore}\n";
  1168.   } elsif($type=~/.xbm$/i || $pic=~/^#define/) {
  1169.     &xbmtops;
  1170.   } elsif($have_ImageMagick) {
  1171.     &run("convert $scr $pg1:-");
  1172.     if(!$pm && $pic=~/^\377\330/ && $have_djpeg) {
  1173.       &run("djpeg $scr$pg2");
  1174.     }
  1175.   } elsif($pic=~/^\377\330/ && $have_djpeg) {
  1176.     &run("djpeg $scr$pg2");
  1177.   } elsif($have_pbmplus || $have_netpbm) {
  1178.     if($pic=~/^GIF/) {
  1179.       &run("$giftopm $scr");
  1180.     } else {
  1181.       &run("anytopnm $scr");
  1182.     }
  1183.     if($opt_g && $pm=~/^P6/) {
  1184.       open(SCRATCH,">$scr");
  1185.       print SCRATCH $pm;
  1186.       close SCRATCH;
  1187.       &run("ppmtopgm $scr");
  1188.     }
  1189.   } elsif($have_sgi) {
  1190.           `$giftopm $pic /tmp/__xXx.rgb 2>/dev/null`;
  1191.           `toppm /tmp/__xXx.rgb /tmp/__xXx.ppm 2>/dev/null`;
  1192.           `/bin/rm -f /tmp/__xXx.rgb /tmp/__xXx.map $pic`;
  1193.           &run("cat /tmp/__xXx.ppm 2>/dev/null");
  1194.   }
  1195.   &pmtops if(!$bm);
  1196.   if(!$bm) {return};
  1197.   $bm=substr($bm,0,$nd);
  1198.   $pad=$nd-length($bm);
  1199.   if($pad) {$bm.="f" x $pad};
  1200.   $bm=~s/(.{60})/$1\n/g;
  1201.   if($have_sgi) {
  1202.      `/bin/rm -f /tmp/__xXx.ppm`;
  1203.   }
  1204. }
  1205.  
  1206.